#!/usr/bin/env python
from unittest import TestCase, main
from litebooks import *

class LiteBooksVirtualTestCase(TestCase):
    def testAPIRequest(self):
        rq_method = 'testMethod'
        input_dict = {'blah':2343, 
                                 'lines' : [
                                     {'line':{'name':'FirstName'}}, 
                                     {'line':{'name':'SecondName'}} 
                                 ]}
        expected_xml = """<?xml version="1.0" ?><request method="testMethod"><blah>2343</blah><lines><line><name>FirstName</name></line><line><name>SecondName</name></line></lines></request>"""
        
        assert APIRequest(rq_method,input_dict).doc.toxml() == expected_xml
        
        
    def testAPIInvoiceXML (self):
        create_invoice = OrderedDict ( [ 
            ('client_id' ,2), 
            ('number', 'INV0007'),
            ('status','draft'),
            ('lines',
                       [  {'line' :  OrderedDict ( [ 
                            ('description','Yard Work'),
                            ('unit_cost',10),
                            ('quantity',4), ])
                            }
                        ,
                        {'line'  : OrderedDict ( [ 
                            ('description','Yard Work'),
                            ('unit_cost',2),
                            ('quantity',3), ])
                        },
                        ]  
                                    
             ),
            
             ])
        
        test_dict = {'client_id' :2, 'number': 'INV0007', 'status':'draft',
                        'lines' : [ {'description':'Yard Work','unit_cost':10, 'quantity':4},
                                    {'description':'Yard Work','unit_cost':2, 'quantity':3}] 
                        }
        inv = APIInvoice (test_dict)
        
        
        p = APIRequest('invoice.create',{'invoice':create_invoice})
        p2 = inv.rq_create
        
        assert p.doc.toxml() == p2.doc.toxml()
        
    def testAPIResponseParse (self):
        input_xml = u"""
<?xml version="1.0" encoding="utf-8"?>
<response xmlns="http://www.freshbooks.com/api/" status="fail">
  <error>Client does not exist.</error>
</response>
"""
        resp = APIResponse(input_xml)
        assert resp.error == 'Client does not exist.'
        
class LiteBooksAPITestCase(TestCase):
    def setUp (self):
        # create a client
        client_dict = { 'first_name':'Test', 'last_name':'Case','organization':'Tests Reloaded',
        'email':'testcase@morp.org'}

        self.client = APIClient (client_dict)
        response = self.client.do_create()
        self.assertFalse (response.error,'Got an error on Client creation: %s' % response.error)
        self.assertEqual (response[APIClient.id_field], self.client.id)
        print '\nSetup Client with id %s' % self.client.id

        # create an invoice for that client
        test_dict = {'client_id' :response['client_id'], 'status':'sent',
                            'lines' : [ {'description':'Yard Work','unit_cost':10, 'quantity':4},
                                        {'description':'Yard Work','unit_cost':2, 'quantity':3}] 
                            }
        
        self.invoice = APIInvoice (test_dict)
        response = self.invoice.do_create()
        self.assertFalse (response.error,'Got an error on Invoice creation: %s' % response.error)
        self.assertEqual (response[APIInvoice.id_field], self.invoice.id)
        print 'Setup Invoice with id %s' % self.invoice.id
        
    def tearDown (self):
        response = self.client.do_delete()
        self.assertFalse (response.error,'Got an error on Client deletion: %s' % response.error)
        print 'Deleted Client with id %s' % self.client.id
        
        response = self.invoice.do_delete()
        self.assertFalse (response.error,'Got an error on Invoice deletion: %s' % response.error)
        print 'Deleted Invoice with id %s' % self.invoice.id
    
    def testSingle(self):
        """Live API tests wrapped in a single test method, to avoid multiple setUps/tearDowns"""
        methods = [getattr(self, method) for method in dir(self) if method.startswith('mytest')]
        for testmethod in methods:
            testmethod()
        pass
        
    def mytestGetInvoiceURL(self):
        """Test getting the public invoice URL"""
        url = self.invoice.client_url
        self.assertTrue(url.startswith(ACCOUNT_URL))
        print 'Public invoice URL:', url
        
        
    def mytestInvoicePDF (self):
        """Test downloading the Invoice PDF"""
        pdf = self.invoice.pdf_stream
        self.assertTrue (len(pdf) > 10000, 'Got a pdf smaller than 10K - there is something wrong')
        
    def mytestGetPaymentURL (self):
        """Test scraping the payment page URL"""
        url = self.invoice.payment_url
        self.assertTrue(url.startswith(ACCOUNT_URL))
        
    def mytestGetPaymentForm (self):
        """Test scraping the PaymentForm"""
        html = self.invoice.payment_form
        self.assertTrue(html.startswith('<form'))
        self.assertTrue(html.endswith('</form>'))
        

if __name__ == '__main__':
    main()
